package model;
/**
 * @author Darko Martinovikj
 * @version 1.0 21.02.2012
 * 
 * Class representing one node of a graph without variables
 *  */
import java.util.LinkedList;

public class NodeTransitionSystem {
	protected int index; 
	protected String name;
	protected LinkedList<EdgeTransitionSystem> neighbors;
	protected LinkedList<EdgeTransitionSystem> parents;
	protected boolean isBadNode;
	
	/**
	 * This method is the constructor of the class.
	 * 
	 * @param int index- the index of the node
	 * @param String name - the name of the node 
	 */
	public NodeTransitionSystem(int index, String name) {
		this.index = index;
		this.name = name;
		neighbors = new LinkedList<EdgeTransitionSystem>();
		parents = new LinkedList<EdgeTransitionSystem>();
		isBadNode=false;
	}
	
	/**
	 * This method is the constructor of the class.
	 * 
	 * @param int index- the index of the node
	 * @param String name - the name of the node 
	 * @param boolean isBadNode - specifies if the node is bad
	 */
	public NodeTransitionSystem(int index, String name, boolean isBadNode) {
		this.index = index;
		this.name = name;
		neighbors = new LinkedList<EdgeTransitionSystem>();
		parents = new LinkedList<EdgeTransitionSystem>();
		this.isBadNode=isBadNode;
	}

	/**
	 * Method for adding a Neighbour to the current node. The data for the transition must be specified.
	 * Automatically the neighbour get a new parent transition
	 * 
	 * @param NodeTransitionSystem neighbour- the node representing the neighbour
	 * @param String transitionName - the name of the transition
	 */
	public void addNeighbor(NodeTransitionSystem neighbour, String transitionName){
		neighbors.addLast(new EdgeTransitionSystem(this, transitionName, neighbour));
		neighbour.addParent(this, transitionName);
	}
	
	/**
	 * Method for adding a Parent Node to the current node. The data for the transition must be specified.
	 * 
	 * @param NodeTransitionSystem parent- the node representing the parent
	 * @param String transitionName - the name of the transition
	 */
	public void addParent(NodeTransitionSystem parent, String transitionName){
		parents.addLast(new EdgeTransitionSystem(parent, transitionName, this));
	}
	
	
	/**
	 * Method for getting the full information for one node: the name and all of the neighbours
	 * 
	 * @return String - the string that contains all of the information of the node
	 */
	public String toStringWithNeightbours() {
		String ret= "Name:"+name+" Neighbours:";
		for (EdgeTransitionSystem edge:neighbors)
		ret+="("+edge+") ";
		return ret;
		
	}

	/**
	 * Method for getting names and all of the parents of the node
	 * 
	 * @return String - the string that contains all of the information of the node
	 */
	public String toStringParents() {
		String ret= " Parents:";
		for (EdgeTransitionSystem edge:parents)
		ret+="("+edge+") ";
		return ret;
		
	}
	
	/**
	 * This method is used to access the index of the node
	 *
	 * @return int - the index of the node
	 */
	public int getIndex() {
		return index;
	}

	/**
	 * This method is used to access the name of the node
	 *
	 * @return int - the name of the node
	 */
	public String getName() {
		return name;
	}

	/**
	 * This method for getting all of the neighbours, more specifically all of the edges starting from current node
	 *
	 * @return LinkedList<EdgeTransitionSystem> - the list of all edges starting from the current node
	 */
	public LinkedList<EdgeTransitionSystem> getNeighbors() {
		return neighbors;
	}

	/**
	 * This method for getting all of the parents, more specifically all of the edges ending in current node
	 *
	 * @return LinkedList<EdgeTransitionSystem> - the list of all edges ending in the current node
	 */
	public LinkedList<EdgeTransitionSystem> getParents() {
		return parents;
	}
	
	/**
	 * This method is used to check if a state is bad
	 *
	 * @return boolean - is the state bad
	 */
	public boolean isBadNode() {
		return isBadNode;
	}

	/**
	 * This method is used for setting the state to be bad
	 *
	 * @param boolean isBadNode - is the state bad
	 */

	public void setBadNode(boolean isBadNode) {
		this.isBadNode = isBadNode;
	}

	/**
	 * This method is used for printing node information
	 *
	 * @return String - the node information
	 */
	@Override
	public String toString(){
		return "{"+index+" "+name+"}";
	}
	
	/**
	 * This method is used for getting the hashCode of a node. This is used for hash tables and other data structures
	 *
	 * @return int  - the hash code of the node
	 */
	@Override
	public int hashCode(){
		return index;
	}
	
	/**
	 * This method is used for checking if two nodes are equal. They are equal if they have the same index
	 *
	 * @return boolean - is the two nodes are equal
	 */
	@Override
	public boolean equals(Object o2){
		return this.hashCode()==o2.hashCode();
	}
	
	/**
	 * This method is used for removing the neighbour from the neighbour list
	 *
	 * @param neighbour- the neighbour edge for removal
	 */
	public void removeNeighbour(EdgeTransitionSystem neighbour){
		neighbors.remove(neighbour);
	}
	
	/**
	 * This method is used for removing the parent from the neighbour list
	 *
	 * @param parent- the parent edge for removal
	 */
	public void removeParent(EdgeTransitionSystem parent){
		parents.remove(parent);
	}
	
}
